/*
 * Copyright (c) 2017,安徽皖通科技股份有限公司 All rights reserved.
 */

package com.wttech.dzzf.process.service.upload;

import cn.com.taiji.sdk.model.comm.protocol.AbstractSdtsRequest;
import cn.com.taiji.sdk.model.comm.protocol.user.CardUploadRequest;
import cn.com.taiji.sdk.model.comm.protocol.user.OBUUploadRequest;
import cn.com.taiji.sdk.model.comm.protocol.user.UserUploadRequest;
import cn.com.taiji.sdk.model.comm.protocol.user.VehicleUploadRequest;
import cn.com.taiji.sdk.tools.JsonTools;
import com.wttech.dzzf.process.constant.ExecuteTable;
import com.wttech.dzzf.process.dao.TransferUserInfoDao;
import com.wttech.dzzf.process.model.UploadRsp;
import com.wttech.dzzf.process.service.base.BaseInfoService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;

import static com.wttech.dzzf.process.constant.UserConstants.*;

/**
 * 数据重传服务实现
 *
 * @author MaShibo
 * @date 2017/12/11.
 */
@Service
public class UploadDataAgainService {

	private static final Logger LOGGER = LoggerFactory.getLogger(UploadDataAgainService.class);

	@Resource
	private TransferUserInfoDao transferUserInfoDao;

	@Resource
	private UploadSingleDataService uploadSingleDataService;

	@Resource
	private BaseInfoService baseInfoService;

	@Resource
	private UploadMonitorService uploadMonitorService;

	@Resource
	private ThreadPoolTaskExecutor executor;

	private ExecuteTable table;

	private void uploadAgain() {
		if (table == null) {
			LOGGER.info("未指定要重传的数据类型");
			return;
		}
		while (true) {
			List<? extends AbstractSdtsRequest> infos = transferUserInfoDao.queryFailureUploadInfos(table, 1, DEFAULT_PROCESS_NUM);
			if (CollectionUtils.isEmpty(infos)) {
				executor.shutdown();
				LOGGER.info("数据重传完成");
				return;
			}
			List<Future<Void>> futures = new ArrayList<>();
			infos.forEach(info -> futures.add(executor.submit(() -> {
				uploadSingleDataService.uploadSdtsInfo(info, table, true);
				return null;
			})));
			baseInfoService.getFutureResult(futures);
		}
	}

	private void processV2() {
		if (table == null) {
			LOGGER.info("尚未指定上传数据类型");
			return;
		}
		while (true) {
			String type = table.getStorePath();
			List<UploadRsp> infoList = transferUserInfoDao.queryFailureRequstJson(type, DEFAULT_PROCESS_NUM);
			if (infoList.isEmpty()) {
				LOGGER.info("数据重传完成");
				return;
			}
			List<Future<Void>> futures = new ArrayList<>(infoList.size());
			infoList.forEach(info -> futures.add(executor.submit(() -> {
				processUploadRsp(info);
				return null;
			})));
			baseInfoService.getFutureResult(futures);
		}
	}

	private void processUploadRsp(UploadRsp info) {
		String json = info.getRequest();
		if (StringUtils.isBlank(json)) {
			return;
		}
		try {
			AbstractSdtsRequest request = JsonTools.json2Object(json, table.getRequestType());
			if (request instanceof VehicleUploadRequest) {
				VehicleUploadRequest vehicle = (VehicleUploadRequest) request;
				LOGGER.info("正在处理{}", vehicle.getId() + "+" + vehicle.getUserId());
				String errorMessage = info.getErrorMessage();

				if (StringUtils.contains(errorMessage, "发行方发行有卡") ||
						StringUtils.contains(errorMessage, "此户车辆信息已经上传")) {
					return;
				}

				if (StringUtils.contains(errorMessage, "用户信息不存在，先上传用户信息")) {
					String userId = vehicle.getUserId();
					UserUploadRequest user = transferUserInfoDao.queryUserInfoById(userId);
					if (user != null) {
						uploadSingleDataService.uploadSdtsInfo(user, ExecuteTable.USER, false);
					}
				}

				if (StringUtils.contains(errorMessage, "vehicleModel格式不正确")){
					vehicle.setVehicleModel(DEFAULT_VEHICLEMODEL);
				}

				if (StringUtils.contains(errorMessage, "id格式不正确")){
					vehicle.setId(DEFAULT_VEHPLATEID);
				}
			}else if(request instanceof OBUUploadRequest){
				OBUUploadRequest obu = (OBUUploadRequest) request;
				String errorMessage = info.getErrorMessage();
				if (StringUtils.contains(errorMessage, "请先上传用户信息")){
					String userId = obu.getUserId();
					UserUploadRequest user = transferUserInfoDao.queryUserInfoById(userId);
					if (user != null){
						uploadSingleDataService.uploadSdtsInfo(user, ExecuteTable.USER, false);
					}
				}
			}else if (request instanceof CardUploadRequest){
				CardUploadRequest card = (CardUploadRequest) request;
				String errorMessage = info.getErrorMessage();
				if (StringUtils.contains(errorMessage, "请先上传用户信息")){
					String userId = card.getUserId();
					UserUploadRequest user = transferUserInfoDao.queryUserInfoById(userId);
					if (user != null){
						uploadSingleDataService.uploadSdtsInfo(user, ExecuteTable.USER, false);
					}
				}
			}
			uploadSingleDataService.uploadSdtsInfo(request, table, true);
		} catch (IOException e) {
			LOGGER.error(e.getMessage(), e);
		}
	}

	@Scheduled(fixedDelay = 1000 * 60)
	public void monitor() {
		if (table == null) {
			return;
		}
		uploadMonitorService.monitor(table);
	}

	private void setTable(ExecuteTable table) {
		this.table = table;
	}

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		UploadDataAgainService service = context.getBean(UploadDataAgainService.class);
		if (args != null) {
			String storePath = args[0];
			Arrays.stream(ExecuteTable.values()).filter(executeTable -> StringUtils.equalsIgnoreCase(storePath, executeTable.getStorePath())).findFirst().ifPresent(service::setTable);
		}
		service.processV2();
	}

}
